#include "stdafx.h"
#include "tray.h"
#include "atlmisc.h"
#include <assert.h>

tray::tray()
: _menu(NULL)
{
	memset(&_tray, 0, sizeof(_tray));
}

tray::tray(UINT uid, HMENU hMenu)
: _menu(hMenu)
{
	memset(&_tray, 0, sizeof(_tray));
	_tray.uID = uid;
	_tray.cbSize = sizeof(_tray);

	AtlLoadString(uid, _tray.szTip, sizeof(_tray.szTip));
}

tray::~tray()
{
	if (_tray.hIcon)
	{
		remove();
	}
}

void tray::set_notify_win(HWND hWnd, UINT msg)
{
	assert(::IsWindow(hWnd));
	_tray.hWnd = hWnd;

	assert(msg >= WM_USER);
	_tray.uCallbackMessage = msg;
}

void tray::set_menu(HMENU hMenu)
{
	if (_menu)
	{
		::DestroyMenu(_menu);
	}

	_menu = hMenu;
}

void tray::set_menu(UINT uid)
{
	if (_menu)
	{
		::DestroyMenu(_menu);
	}

	_tray.uID = uid;
}

bool tray::set(UINT uid, const char* tip)
{
	UINT msg = NIM_ADD;
	_tray.uFlags = 0;

	if (_tray.hIcon)
	{
		msg = NIM_MODIFY;
	}

	_tray.hIcon = AtlLoadIcon(uid);
	_tray.uFlags |= NIF_ICON;

	if (tip)
	{
		_tcsncpy(_tray.szTip, tip, sizeof(_tray.szTip));
		_tray.uFlags |= NIF_TIP;
	}

	if (_tray.hWnd && _tray.uCallbackMessage)
	{
		_tray.uFlags |= NIF_MESSAGE;
	}

	return Shell_NotifyIcon(msg, &_tray);
}

bool tray::set(HICON hicon, const char* tip)
{
	UINT msg = NIM_ADD;
	_tray.uFlags = 0;

	if (_tray.hIcon)
	{
		msg = NIM_MODIFY;	
	}

	_tray.uFlags |= NIF_ICON;
	_tray.hIcon = hicon;

	if (tip)
	{
		_tcsncpy(_tray.szTip, tip, sizeof(_tray.szTip));
		_tray.uFlags |= NIF_TIP;
	}
	
	if (_tray.hWnd && _tray.uCallbackMessage)
	{
		_tray.uFlags |= NIF_MESSAGE;
	}

	return Shell_NotifyIcon(msg, &_tray);
}

bool tray::remove()
{
	bool ret = true;

	if (_tray.hIcon)
	{
		if (ret = Shell_NotifyIcon(NIM_DELETE, &_tray))
		{
			_tray.hIcon = NULL;
		}
	}

	return ret;
}

LRESULT tray::notify(WPARAM wparam, LPARAM lparam)
{
	if (wparam != _tray.uID || (lparam != WM_RBUTTONUP && lparam != WM_LBUTTONDBLCLK))
	{
		return 0;
	}

	// if 
	if (NULL == _menu)
	{
		_menu = ::LoadMenu(ModuleHelper::GetResourceInstance(), ATL::_U_STRINGorID(_tray.uID).m_lpstr);
		if (NULL == _menu)
		{
			return 0;
		}
	}
	
	HMENU tMenu = ::GetSubMenu(_menu, 0);
	//HMENU tMenu = _menu;
	if (NULL == tMenu)
	{
		return 0;
	}

	if (lparam == WM_RBUTTONUP) 
	{

		// Make first menu item the default (bold font)
		::SetMenuDefaultItem(tMenu, 0, TRUE);

		// Display the menu at the current mouse location. There's a "bug"
		// (Microsoft calls it a feature) in Windows 95 that requires calling
		// SetForegroundWindow. To find out more, search for Q135788 in MSDN.
		//
		CPoint mouse;
		GetCursorPos(&mouse);
		::SetForegroundWindow(_tray.hWnd);	
		::TrackPopupMenu(tMenu, 0, mouse.x, mouse.y, 0, _tray.hWnd, NULL);
	} 
	else  // double click: execute first menu item
	{
		::SendMessage(_tray.hWnd, WM_COMMAND, ::GetMenuItemID(_menu, 0), 0);
	}

	return 1; // handled
}